#!/usr/bin/python3
# -*- encoding:utf-8 -*-
# author: king
# create date time: 2024/4/14 下午12:29

"""
概念：
责任链模式（Chain of Responsibility Pattern）是一种行为型设计模式。
用于将请求从一个对象传递到另一个对象，直到请求被处理为止。
在责任链模式中，多个对象组成一个链，每个对象都有机会处理请求，如果一个对象不能处理请求，它会将请求传递给链中的下一个对象，直到请求被处理为止。

功能：
责任链模式的主要功能是将请求从一个对象传递到另一个对象，直到请求被处理为止。
这种模式能够让多个对象共同处理请求，从而实现请求的处理分担和简化。

优点：
降低系统耦合度：责任链模式将请求发送者和请求处理者解耦，使多个对象都有机会处理请求，从而降低系统的耦合度。
灵活性好：责任链模式可以动态地组合和增加责任的对象，从而使系统更加灵活。
可扩展性好：责任链模式可以方便地扩展新的请求处理者，从而增强系统的可扩展性。

缺点：
处理请求可能不确定：由于责任链中的请求处理者是动态的，因此请求可能被多个处理者处理，从而可能导致最终的请求处理结果不确定。
性能问题：如果责任链中的处理者过多，可能会影响系统的性能。

应用场景：
请求需要被多个对象处理时，而且每个对象处理请求的方式不同。
在系统中需要动态地增加或删除请求处理者时。
在系统中需要分担和简化请求处理时。

使用方式：
定义一个请求基类，提供设置请求和获取请求的方法。
定义一个处理请求的抽象基类，提供处理请求的方法，并包含一个指向下一个处理者的指针。
定义具体的处理请求的类，并继承抽象基类，实现处理请求的方法。
在客户端代码中组合处理请求的链，并发送请求。

场景：
概述Python3使用枚举（enum）的方式实现责任链设计模式（Python3中的枚举属于顺序执行，满足责任链的逻辑设计）。
假设公司内有 1 个总经理（GeneralManager）、2 个部门经理（DepartmentManager）、每个部门经理下面有 1 个小组，每个小组 6 个人，6 个组员中其中有 1 位是小组长（GroupManager）。

请假系统如下：
3天及3天以内请假小组长可以有权限直接处理，通过或者不通过请假。
3天以上 - 7天包含7天之内小组长是没有权利处理的，只能部门经理才可以处理。
7天以上那么只能上报到总经理处才可以处理。
组员有时候需要通过审批系统去请假，假设有位小组员需要请10天假，那么他请假的流程如下：

他将先报告给他们组的小组长，然后小组长无法处理此次审批，小组长再向上报告给负责他的部门经理。
10天假，他们的部门经理也无法处理此次审批请求，所以部门经理将继续上报给总经理，由总经理来处理此次请假审批。
总经理有权利处理此次审批请求，在权限范围内，总经理将直接予以处理。
反馈给小组员，他的这次请假是否通过。
"""

from enum import Enum, unique
from typing import Optional, Union
from loguru import logger
import os
import sys


@unique
class ApproveTypeEnum(Enum):
    """
    请求类型的枚举
    """
    days_off = "请假"
    go_out = "外出"
    business_trip = "出差"


class ManagerPermissionOnApproveDays(Enum):
    """
    管理员审批天数
    """
    group_manager = 3
    department_manager = 7
    business_trip = None


class ApprovalRequest:
    """
    审批请求类
    """

    def __init__(self, approval_type: str, approval_content: str, approval_number: int):
        self.aproval_type = approval_type  # 审批类型
        self.approval_content = approval_content  # 审批内容
        self.approval_number = approval_number  # 天数


class GroupManager:
    """
    组长级别
    """

    def __init__(self, name: str = '组长'):
        self.name = name

    def handle_approval(self, approval_obj: ApprovalRequest) -> Union[str, bool]:
        """
        组长级别处理审批请求
        :param approval_obj: 审批对象
        :return: 处理结果。或者级别不够，需要交由上一级处理
        :author: king
        :create date time: 2024/4/14 下午12:39
        """
        if all([
            approval_obj.aproval_type == ApproveTypeEnum.days_off.value,
            approval_obj.approval_number <= ManagerPermissionOnApproveDays.group_manager.value,
        ]):
            approval_results = f"""
                职位：{self.name} | 处理审批的内容为：【{approval_obj.approval_content}】，处理请假的天数为：{approval_obj.approval_number}，此级别可以处理审批，予以接受
            """
            return approval_results

        else:
            approval_results = f"""
                职位：{self.name} | 处理审批的内容为：【{approval_obj.approval_content}】，处理请假的天数为：{approval_obj.approval_number}，此级别不能处理，审批继续上报'
            """
            logger.warning(approval_results)
            return False


class DepartmentManager:
    """
    部门经理级别
    """

    def __init__(self, name='部门经理'):
        self.name = name

    def handle_approval(self, approval_obj: ApprovalRequest) -> Union[str, bool]:
        """
        部门经理审批请求
        :param approval_obj: 审批对象
        :return: 处理结果。或者级别不够，需要交由上一级处理
        :author: king
        :create date time: 2024/4/14 下午12:48
        """
        if all([
            approval_obj.aproval_type == ApproveTypeEnum.days_off.value,
            approval_obj.approval_number <= ManagerPermissionOnApproveDays.department_manager.value,
        ]):
            approval_results = f"""
                职位：{self.name} | 处理审批的内容为：【{approval_obj.approval_content}】，处理请假的天数为：{approval_obj.approval_number}，此级别可以处理审批，予以接受
            """
            return approval_results

        else:
            approval_results = f"""
                职位：{self.name} | 处理审批的内容为：【{approval_obj.approval_content}】，处理请假的天数为：{approval_obj.approval_number}，此级别不能处理，审批继续上报'
            """
            logger.warning(approval_results)
            return False


class GeneralManager:
    """
    总经理级别
    """

    def __init__(self, name='总经理'):
        self.name = name

    def handle_approval(self, approval_obj: ApprovalRequest) -> Union[str, bool]:
        """
        总经理审批请求
        :param approval_obj: 审批对象
        :return: 处理结果
        :author: king
        :create date time: 2024/4/14 下午12:50
        """
        if approval_obj.aproval_type == ApproveTypeEnum.days_off.value:
            approval_results = f"""
                职位：{self.name} | 处理审批的内容为：【{approval_obj.approval_content}】，处理请假的天数为：{approval_obj.approval_number}，此级别可以处理，予以接受。'
            """
            return approval_results


class ApprovalManagerEnum(Enum):
    """
    各个级别权限的枚举类
    """
    group_manager = GroupManager()
    department_manager = DepartmentManager()
    general_manager = GeneralManager()


class HandleApprovalClass:
    """
    专门处理审批的类
    """

    @staticmethod
    def send_approval(approval_obj: ApprovalRequest):
        """
        :param approval_obj: 审批对象
        :return:
        :author: king
        :create date time: 2024/4/14 下午12:55
        """
        for handle_approval_manager in ApprovalManagerEnum:

            handle_obj = handle_approval_manager.value

            manager_handle_results = handle_obj.handle_approval(approval_obj)
            if isinstance(manager_handle_results, str) and manager_handle_results:
                return manager_handle_results


def main():
    """ 程序入口 """
    approval_type = ApproveTypeEnum.days_off.value
    approval_number = 7
    approval_content = f"组员: WLL， 需要请 {approval_number} 天假。"
    approval_obj = ApprovalRequest(approval_type, approval_content, approval_number)

    handle_results = HandleApprovalClass.send_approval(approval_obj)
    logger.info(handle_results)


if __name__ == "__main__":
    main()
